package palms.authserver;

import java.io.IOException;
import java.net.Socket;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;

import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SealedObject;
import javax.crypto.spec.SecretKeySpec;

import palms.exceptions.InvalidClassMessage;
import palms.exceptions.InvalidTicketMessage;
import palms.exceptions.InvalidUserMessage;
import palms.messages.AuthRequest;
import palms.messages.AuthResponse;
import palms.messages.TicketTGS;
import palms.security.PalmsSecurityManager;

public class KASWorker implements Runnable {

	private Socket s;
	private AuthLogic al;
	
	public KASWorker(Socket s, AuthLogic al){
		this.s = s;
		this.al = al;
	}
	
	@Override
	public void run() {
		try {
			
			AuthRequest ar = AuthRequest.receiveTroughSocket(s);
			this.processAuthRequest(ar);
				
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidClassMessage e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidUserMessage e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidTicketMessage e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void processAuthRequest(AuthRequest req) throws IOException,NoSuchAlgorithmException, NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException{
		
		System.out.println("[KAS]-->Processing an Authentication Request for user: " + req.getUsername());
		
		String username = req.getUsername();

		if(al.getUserlist().containsKey(username)){
			
			SecretKeySpec clientKey = PalmsSecurityManager.getKeyFromString(al.getUserlist().get(username));
			SecretKeySpec sessionkey = PalmsSecurityManager.getSessionKey();
			SecretKeySpec tgskey = al.getKeyTGS();
			TicketTGS tgsticket = new TicketTGS(username, s.getInetAddress().getHostAddress(), Calendar.getInstance().getTimeInMillis() + 180000, sessionkey);
			
			SealedObject sealedticket = PalmsSecurityManager.SealObjectWithK(tgsticket, tgskey);
			SealedObject sealedkey = PalmsSecurityManager.SealObjectWithK(sessionkey, clientKey);
			
			System.out.println();
			System.out.println("[KAS]-->The client's " + username + " secret key is: " + PalmsSecurityManager.asHex(clientKey.getEncoded()));
			System.out.println("[KAS]-->Generated Client/TGS session key: " + PalmsSecurityManager.asHex(sessionkey.getEncoded()));
			System.out.println("[KAS]-->TGS key is: " + PalmsSecurityManager.asHex(tgskey.getEncoded()));
			System.out.println();
			System.out.println("[KAS]-->Sealed TGS session key: " + sealedkey);
			System.out.println("[KAS]-->TGS ticket: " + sealedticket);
			System.out.println();
			
			AuthResponse response = new AuthResponse(sealedticket, sealedkey);
			
			System.out.println("[KAS]-->Sending ticket and session key");
			System.out.println();
			response.sendTroughSocket(s);
			
		}else{
			PalmsSecurityManager.sendError(s, new InvalidUserMessage());
		}

	}

}
